/*
 * BlockFileWithByteAccess.h
 *
 *  Created on: Nov 24, 2012
 *      Author: m
 */

#ifndef BLOCKFILEWITHBYTEACCESS_H_
#define BLOCKFILEWITHBYTEACCESS_H_

#include "FixedSizeBlockFile.h"

namespace physical
{

class BlockFileWithByteAccess: public physical::FixedSizeBlockFile
{
public:

    /**
     * Constructor
     *
     * Si no se indica "filename" ni "openmode", no se asocia ningún
     *  archivo físico al BlockFile. Si solo se indica el filename
     *  se asocia dicho archivo al BlockFile y se lo abre en el modo
     *  por defecto ( in | out ). Si se indican todos los parámetros
     *  se abre el archivo "filename" en el modo "openmode" indicado.
     *
     * @param blockSize Tamaño de bloque
     * @param filename  Nombre del archivo de bloques (opcional)
     * @param mode      Modo de apertura del archivo (opcional)
     */
    BlockFileWithByteAccess( size_t blockSize, const char filename[] = NULL, openmode  mode = defaulOpenmode ) :
        FixedSizeBlockFile( blockSize, filename, mode )
    {
    }

    /**
     * Destructor
     */
    virtual ~BlockFileWithByteAccess()
    {
    }

    /**
     * Permite lectura directa de un byte específico de un bloque
     *
     * @param blockNbr   Número de bloque al que acceder
     * @param byteOffset Offset del byte (relativo al bloque) a acceder
     * @return  El byte leido
     */
    byte readByte( blockNumber blockNbr, size_t byteOffset )
    {
        byte buffer;

        if ( m_blockSize <= 0 )
            throw InvalidBlockSizeException();

        blockNumber nextPosition = blockNbr * m_blockSize + byteOffset;
        m_blockSource.seekp( nextPosition );

        m_blockSource.read( &buffer, 1 );

        return buffer;
    }

    /**
     * Permite escritura directa de un byte específico de un bloque
     *
     * @param blockNbr   Número de bloque al que acceder
     * @param byteOffset Offset del byte (relativo al bloque) a acceder
     * @param buffer     Byte a escribir
     */
    void writeByte( blockNumber blockNbr, size_t byteOffset, const byte buffer )
    {
        if ( m_blockSize <= 0 )
            throw InvalidBlockSizeException();

        blockNumber nextPosition = blockNbr * m_blockSize + byteOffset;
        m_blockSource.seekp( nextPosition );

        m_blockSource.write( &buffer, 1 );
    }
};

} /* namespace physical */
#endif /* BLOCKFILEWITHBYTEACCESS_H_ */
